/*
 * This file is part of Ext JS 3.4 Copyright (c) 2011-2013 Sencha Inc Contact: http://www.sencha.com/contact GNU General Public License Usage This file may be
 * used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in
 * the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met:
 * http://www.gnu.org/copyleft/gpl.html. If you are unsure which license is appropriate for your use, please contact the sales department at
 * http://www.sencha.com/contact. Build date: 2013-04-03 15:07:25
 */
/**
 * @class Ext
 */

Ext.ns("Ext.grid", "Ext.list", "Ext.dd", "Ext.tree", "Ext.form", "Ext.menu", "Ext.state", "Ext.layout.boxOverflow", "Ext.app", "Ext.ux", "Ext.chart", "Ext.direct", "Ext.slider");
/**
 * Namespace alloted for extensions to the framework.
 * 
 * @property ux
 * @type Object
 */

Ext.apply(Ext, function()
{
	var E = Ext, idSeed = 0, scrollWidth = null;

	return {
		/**
		 * A reusable empty function
		 * 
		 * @property
		 * @type Function
		 */
		emptyFn: function()
		{
		},

		/**
		 * URL to a 1x1 transparent gif image used by Ext to create inline icons with CSS background images. In older versions of IE, this defaults to
		 * "http://extjs.com/s.gif" and you should change this to a URL on your server. For other browsers it uses an inline data URL.
		 * 
		 * @type String
		 */
		BLANK_IMAGE_URL: Ext.isIE6 || Ext.isIE7 || Ext.isAir ? 'http:/' + '/www.extjs.com/s.gif' : '',

		extendX: function( supr, fn )
		{
			return Ext.extend(supr, fn(supr.prototype));
		},

		/**
		 * Returns the current HTML document object as an {@link Ext.Element}.
		 * 
		 * @return Ext.Element The document
		 */
		getDoc: function()
		{
			return Ext.get(document);
		},

		/**
		 * Utility method for validating that a value is numeric, returning the specified default value if it is not.
		 * 
		 * @param {Mixed} value Should be a number, but any type will be handled appropriately
		 * @param {Number} defaultValue The value to return if the original value is non-numeric
		 * @return {Number} Value, if numeric, else defaultValue
		 */
		num: function( v, defaultValue )
		{
			v = Number(Ext.isEmpty(v) || Ext.isArray(v) || typeof v == 'boolean' || (typeof v == 'string' && v.trim().length == 0) ? NaN : v);
			return isNaN(v) ? defaultValue : v;
		},

		/**
		 * <p>Utility method for returning a default value if the passed value is empty.</p> <p>The value is deemed to be empty if it is<div
		 * class="mdetail-params"><ul> <li>null</li> <li>undefined</li> <li>an empty array</li> <li>a zero length string (Unless the <tt>allowBlank</tt>
		 * parameter is <tt>true</tt>)</li> </ul></div>
		 * 
		 * @param {Mixed} value The value to test
		 * @param {Mixed} defaultValue The value to return if the original value is empty
		 * @param {Boolean} allowBlank (optional) true to allow zero length strings to qualify as non-empty (defaults to false)
		 * @return {Mixed} value, if non-empty, else defaultValue
		 */
		value: function( v, defaultValue, allowBlank )
		{
			return Ext.isEmpty(v, allowBlank) ? defaultValue : v;
		},

		/**
		 * Escapes the passed string for use in a regular expression
		 * 
		 * @param {String} str
		 * @return {String}
		 */
		escapeRe: function( s )
		{
			return s.replace(/([-.*+?^${}()|[\]\/\\])/g, "\\$1");
		},

		sequence: function( o, name, fn, scope )
		{
			o[name] = o[name].createSequence(fn, scope);
		},

		/**
		 * Applies event listeners to elements by selectors when the document is ready. The event name is specified with an <tt>&#64;</tt> suffix.
		 * 
		 * <pre><code>
		 * Ext.addBehaviors(
		 * {
		 * 	// add a listener for click on all anchors in element with id foo
		 * 	'#foo a @click': function( e, t )
		 * 	{
		 * 		// do something
		 * 	},
		 * 
		 * 	// add the same listener to multiple selectors (separated by comma BEFORE the  @)
		 * 	'#foo a, #bar span.some-class @mouseover': function()
		 * 	{
		 * 		// do something
		 * 	}
		 * });
		 * </code></pre>
		 * 
		 * @param {Object} obj The list of behaviors to apply
		 */
		addBehaviors: function( o )
		{
			if( !Ext.isReady )
			{
				Ext.onReady(function()
				{
					Ext.addBehaviors(o);
				});
			}
			else
			{
				var cache = {}, // simple cache for applying multiple behaviors to same selector does query multiple times
				parts, b, s;
				for( b in o )
				{
					if( (parts = b.split('@'))[1] )
					{ // for Object prototype breakers
						s = parts[0];
						if( !cache[s] )
						{
							cache[s] = Ext.select(s);
						}
						cache[s].on(parts[1], o[b]);
					}
				}
				cache = null;
			}
		},

		/**
		 * Utility method for getting the width of the browser scrollbar. This can differ depending on operating system settings, such as the theme or font size.
		 * 
		 * @param {Boolean} force (optional) true to force a recalculation of the value.
		 * @return {Number} The width of the scrollbar.
		 */
		getScrollBarWidth: function( force )
		{
			if( !Ext.isReady )
			{
				return 0;
			}

			if( force === true || scrollWidth === null )
			{
				// Append our div, do our calculation and then remove it
				var div = Ext.getBody().createChild('<div class="x-hide-offsets" style="width:100px;height:50px;overflow:hidden;"><div style="height:200px;"></div></div>'), child = div.child('div', true);
				var w1 = child.offsetWidth;
				div.setStyle('overflow', (Ext.isWebKit || Ext.isGecko) ? 'auto' : 'scroll');
				var w2 = child.offsetWidth;
				div.remove();
				// Need to add 2 to ensure we leave enough space
				scrollWidth = w1 - w2 + 2;
			}
			return scrollWidth;
		},

		// deprecated
		combine: function()
		{
			var as = arguments, l = as.length, r = [];
			for( var i = 0; i < l; i++ )
			{
				var a = as[i];
				if( Ext.isArray(a) )
				{
					r = r.concat(a);
				}
				else if( a.length !== undefined && !a.substr )
				{
					r = r.concat(Array.prototype.slice.call(a, 0));
				}
				else
				{
					r.push(a);
				}
			}
			return r;
		},

		/**
		 * Copies a set of named properties fom the source object to the destination object. <p>example:
		 * 
		 * <pre><code>
		 * ImageComponent = Ext.extend(Ext.BoxComponent,
		 * {
		 * 	initComponent: function()
		 * 	{
		 * 		this.autoEl =
		 * 		{
		 * 			tag: 'img'
		 * 		};
		 * 		MyComponent.superclass.initComponent.apply(this, arguments);
		 * 		this.initialBox = Ext.copyTo({}, this.initialConfig, 'x,y,width,height');
		 * 	}
		 * });
		 * </code></pre>
		 * 
		 * @param {Object} dest The destination object.
		 * @param {Object} source The source object.
		 * @param {Array/String} names Either an Array of property names, or a comma-delimited list of property names to copy.
		 * @return {Object} The modified object.
		 */
		copyTo: function( dest, source, names )
		{
			if( typeof names == 'string' )
			{
				names = names.split(/[,;\s]/);
			}
			Ext.each(names, function( name )
			{
				if( source.hasOwnProperty(name) )
				{
					dest[name] = source[name];
				}
			}, this);
			return dest;
		},

		/**
		 * Attempts to destroy any objects passed to it by removing all event listeners, removing them from the DOM (if applicable) and calling their destroy
		 * functions (if available). This method is primarily intended for arguments of type {@link Ext.Element} and {@link Ext.Component}, but any subclass of
		 * {@link Ext.util.Observable} can be passed in. Any number of elements and/or components can be passed into this function in a single call as separate
		 * arguments.
		 * 
		 * @param {Mixed...} args An {@link Ext.Element}, {@link Ext.Component}, or an Array of either of these to destroy
		 */
		destroy: function()
		{
			Ext.each(arguments, function( arg )
			{
				if( arg )
				{
					if( Ext.isArray(arg) )
					{
						this.destroy.apply(this, arg);
					}
					else if( typeof arg.destroy == 'function' )
					{
						arg.destroy();
					}
					else if( arg.dom )
					{
						arg.remove();
					}
				}
			}, this);
		},

		/**
		 * Attempts to destroy and then remove a set of named properties of the passed object.
		 * 
		 * @param {Object} o The object (most likely a Component) who's properties you wish to destroy.
		 * @param {Mixed} arg1 The name of the property to destroy and remove from the object.
		 * @param {Mixed} etc... More property names to destroy and remove.
		 */
		destroyMembers: function( o, arg1, arg2, etc )
		{
			for( var i = 1, a = arguments, len = a.length; i < len; i++ )
			{
				Ext.destroy(o[a[i]]);
				delete o[a[i]];
			}
		},

		/**
		 * Creates a copy of the passed Array with falsy values removed.
		 * 
		 * @param {Array/NodeList} arr The Array from which to remove falsy values.
		 * @return {Array} The new, compressed Array.
		 */
		clean: function( arr )
		{
			var ret = [];
			Ext.each(arr, function( v )
			{
				if( !!v )
				{
					ret.push(v);
				}
			});
			return ret;
		},

		/**
		 * Creates a copy of the passed Array, filtered to contain only unique values.
		 * 
		 * @param {Array} arr The Array to filter
		 * @return {Array} The new Array containing unique values.
		 */
		unique: function( arr )
		{
			var ret = [], collect = {};

			Ext.each(arr, function( v )
			{
				if( !collect[v] )
				{
					ret.push(v);
				}
				collect[v] = true;
			});
			return ret;
		},

		/**
		 * Recursively flattens into 1-d Array. Injects Arrays inline.
		 * 
		 * @param {Array} arr The array to flatten
		 * @return {Array} The new, flattened array.
		 */
		flatten: function( arr )
		{
			var worker = [];
			function rFlatten( a )
			{
				Ext.each(a, function( v )
				{
					if( Ext.isArray(v) )
					{
						rFlatten(v);
					}
					else
					{
						worker.push(v);
					}
				});
				return worker;
			}
			return rFlatten(arr);
		},

		/**
		 * Returns the minimum value in the Array.
		 * 
		 * @param {Array|NodeList} arr The Array from which to select the minimum value.
		 * @param {Function} comp (optional) a function to perform the comparision which determines minimization. If omitted the "<" operator will be used. Note:
		 *        gt = 1; eq = 0; lt = -1
		 * @return {Object} The minimum value in the Array.
		 */
		min: function( arr, comp )
		{
			var ret = arr[0];
			comp = comp || function( a, b )
			{
				return a < b ? -1 : 1;
			};
			Ext.each(arr, function( v )
			{
				ret = comp(ret, v) == -1 ? ret : v;
			});
			return ret;
		},

		/**
		 * Returns the maximum value in the Array
		 * 
		 * @param {Array|NodeList} arr The Array from which to select the maximum value.
		 * @param {Function} comp (optional) a function to perform the comparision which determines maximization. If omitted the ">" operator will be used. Note: gt =
		 *        1; eq = 0; lt = -1
		 * @return {Object} The maximum value in the Array.
		 */
		max: function( arr, comp )
		{
			var ret = arr[0];
			comp = comp || function( a, b )
			{
				return a > b ? 1 : -1;
			};
			Ext.each(arr, function( v )
			{
				ret = comp(ret, v) == 1 ? ret : v;
			});
			return ret;
		},

		/**
		 * Calculates the mean of the Array
		 * 
		 * @param {Array} arr The Array to calculate the mean value of.
		 * @return {Number} The mean.
		 */
		mean: function( arr )
		{
			return arr.length > 0 ? Ext.sum(arr) / arr.length : undefined;
		},

		/**
		 * Calculates the sum of the Array
		 * 
		 * @param {Array} arr The Array to calculate the sum value of.
		 * @return {Number} The sum.
		 */
		sum: function( arr )
		{
			var ret = 0;
			Ext.each(arr, function( v )
			{
				ret += v;
			});
			return ret;
		},

		/**
		 * Partitions the set into two sets: a true set and a false set. Example: Example2:
		 * 
		 * <pre><code>
		 * // Example 1:
		 * Ext.partition(
		 * [
		 *     true, false, true, true, false
		 * ]); // [[true, true, true], [false, false]]
		 * 
		 * // Example 2:
		 * Ext.partition(Ext.query(&quot;p&quot;), function( val )
		 * {
		 * 	return val.className == &quot;class1&quot;
		 * });
		 * // true are those paragraph elements with a className of &quot;class1&quot;,
		 * // false set are those that do not have that className.
		 * </code></pre>
		 * 
		 * @param {Array|NodeList} arr The array to partition
		 * @param {Function} truth (optional) a function to determine truth. If this is omitted the element itself must be able to be evaluated for its
		 *        truthfulness.
		 * @return {Array} [true<Array>,false<Array>]
		 */
		partition: function( arr, truth )
		{
			var ret =
			[
			    [], []
			];
			Ext.each(arr, function( v, i, a )
			{
				ret[(truth && truth(v, i, a)) || (!truth && v) ? 0 : 1].push(v);
			});
			return ret;
		},

		/**
		 * Invokes a method on each item in an Array.
		 * 
		 * <pre><code>
		 * // Example:
		 * Ext.invoke(Ext.query(&quot;p&quot;), &quot;getAttribute&quot;, &quot;id&quot;);
		 * // [el1.getAttribute(&quot;id&quot;), el2.getAttribute(&quot;id&quot;), ..., elN.getAttribute(&quot;id&quot;)]
		 * </code></pre>
		 * 
		 * @param {Array|NodeList} arr The Array of items to invoke the method on.
		 * @param {String} methodName The method name to invoke.
		 * @param {...*} args Arguments to send into the method invocation.
		 * @return {Array} The results of invoking the method on each item in the array.
		 */
		invoke: function( arr, methodName )
		{
			var ret = [], args = Array.prototype.slice.call(arguments, 2);
			Ext.each(arr, function( v, i )
			{
				if( v && typeof v[methodName] == 'function' )
				{
					ret.push(v[methodName].apply(v, args));
				}
				else
				{
					ret.push(undefined);
				}
			});
			return ret;
		},

		/**
		 * Plucks the value of a property from each item in the Array
		 * 
		 * <pre><code>
		 * // Example:
		 * Ext.pluck(Ext.query(&quot;p&quot;), &quot;className&quot;); // [el1.className, el2.className, ..., elN.className]
		 * </code></pre>
		 * 
		 * @param {Array|NodeList} arr The Array of items to pluck the value from.
		 * @param {String} prop The property name to pluck from each element.
		 * @return {Array} The value from each item in the Array.
		 */
		pluck: function( arr, prop )
		{
			var ret = [];
			Ext.each(arr, function( v )
			{
				ret.push(v[prop]);
			});
			return ret;
		},

		/**
		 * <p>Zips N sets together.</p>
		 * 
		 * <pre><code>
		 * // Example 1:
		 * Ext.zip(
		 * [
		 *     1, 2, 3
		 * ],
		 * [
		 *     4, 5, 6
		 * ]); // [[1,4],[2,5],[3,6]]
		 * // Example 2:
		 * Ext.zip(
		 * [
		 *     &quot;+&quot;, &quot;-&quot;, &quot;+&quot;
		 * ],
		 * [
		 *     12, 10, 22
		 * ],
		 * [
		 *     43, 15, 96
		 * ], function( a, b, c )
		 * {
		 * 	return &quot;$&quot; + a + &quot;&quot; + b + &quot;.&quot; + c
		 * }); // [&quot;$+12.43&quot;, &quot;$-10.15&quot;, &quot;$+22.96&quot;]
		 * </code></pre>
		 * 
		 * @param {Arrays|NodeLists} arr This argument may be repeated. Array(s) to contribute values.
		 * @param {Function} zipper (optional) The last item in the argument list. This will drive how the items are zipped together.
		 * @return {Array} The zipped set.
		 */
		zip: function()
		{
			var parts = Ext.partition(arguments, function( val )
			{
				return typeof val != 'function';
			}), arrs = parts[0], fn = parts[1][0], len = Ext.max(Ext.pluck(arrs, "length")), ret = [];

			for( var i = 0; i < len; i++ )
			{
				ret[i] = [];
				if( fn )
				{
					ret[i] = fn.apply(fn, Ext.pluck(arrs, i));
				}
				else
				{
					for( var j = 0, aLen = arrs.length; j < aLen; j++ )
					{
						ret[i].push(arrs[j][i]);
					}
				}
			}
			return ret;
		},

		/**
		 * This is shorthand reference to {@link Ext.ComponentMgr#get}. Looks up an existing {@link Ext.Component Component} by {@link Ext.Component#id id}
		 * 
		 * @param {String} id The component {@link Ext.Component#id id}
		 * @return Ext.Component The Component, <tt>undefined</tt> if not found, or <tt>null</tt> if a Class was found.
		 */
		getCmp: function( id )
		{
			return Ext.ComponentMgr.get(id);
		},

		/**
		 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash, you may want to set this to true.
		 * 
		 * @type Boolean
		 */
		useShims: E.isIE6 || (E.isMac && E.isGecko2),

		// inpired by a similar function in mootools library
		/**
		 * Returns the type of object that is passed in. If the object passed in is null or undefined it return false otherwise it returns one of the following
		 * values:<div class="mdetail-params"><ul> <li><b>string</b>: If the object passed is a string</li> <li><b>number</b>: If the object passed is a
		 * number</li> <li><b>boolean</b>: If the object passed is a boolean value</li> <li><b>date</b>: If the object passed is a Date object</li> <li><b>function</b>:
		 * If the object passed is a function reference</li> <li><b>object</b>: If the object passed is an object</li> <li><b>array</b>: If the object passed
		 * is an array</li> <li><b>regexp</b>: If the object passed is a regular expression</li> <li><b>element</b>: If the object passed is a DOM Element</li>
		 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li> <li><b>textnode</b>: If the object passed is a DOM text node and contains something
		 * other than whitespace</li> <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li> </ul></div>
		 * 
		 * @param {Mixed} object
		 * @return {String}
		 */
		type: function( o )
		{
			if( o === undefined || o === null )
			{
				return false;
			}
			if( o.htmlElement )
			{
				return 'element';
			}
			var t = typeof o;
			if( t == 'object' && o.nodeName )
			{
				switch( o.nodeType )
				{
				case 1:
					return 'element';
				case 3:
					return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
				}
			}
			if( t == 'object' || t == 'function' )
			{
				switch( o.constructor )
				{
				case Array:
					return 'array';
				case RegExp:
					return 'regexp';
				case Date:
					return 'date';
				}
				if( typeof o.length == 'number' && typeof o.item == 'function' )
				{
					return 'nodelist';
				}
			}
			return t;
		},

		intercept: function( o, name, fn, scope )
		{
			o[name] = o[name].createInterceptor(fn, scope);
		},

		// internal
		callback: function( cb, scope, args, delay )
		{
			if( typeof cb == 'function' )
			{
				if( delay )
				{
					cb.defer(delay, scope, args || []);
				}
				else
				{
					cb.apply(scope, args || []);
				}
			}
		}
	};
}());


